package com.example.ch03xyztwocom.utils;

import com.auth0.jwt.algorithms.Algorithm;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.Charset;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.UUID;

public class AESTool {
	public static final String AES = "AES";
	public static final Charset UTF8 = Charset.forName("UTF-8");
	private static final char[] HEX_CHARS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b',
			'c', 'd', 'e', 'f' };
	private byte[] rawKey;
	public AESTool(String key) {
		try {
			rawKey = getRawKey(key.getBytes(UTF8));
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}
	public String encrypt(String text) throws Exception {
		byte[] result = encrypt(rawKey, text.getBytes(UTF8));
		return encodeHex(result);
	}
	public String decrypt(String encrypted) throws Exception {
		byte[] result = decrypt(rawKey, decodeByte(encrypted));
		return new String(result, UTF8);
	}
	public static String encrypt(String key, String text) throws Exception {
		byte[] rawKey = getRawKey(key.getBytes(UTF8));
		byte[] result = encrypt(rawKey, text.getBytes(UTF8));
		return encodeHex(result);
	}
	private static byte[] getRawKey(byte[] seed) throws NoSuchAlgorithmException {
		KeyGenerator kgen = KeyGenerator.getInstance(AES);
		SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
		sr.setSeed(seed);
		kgen.init(128, sr);
		SecretKey skey = kgen.generateKey();
		return skey.getEncoded();
	}
	public static String decrypt(String key, String encrypted) throws Exception {
		byte[] rawKey = getRawKey(key.getBytes(UTF8));
		byte[] result = decrypt(rawKey, decodeByte(encrypted));
		return new String(result, UTF8);
	}
	private static byte[] encrypt(byte[] raw, byte[] clear) throws Exception {
		SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
		Cipher cipher = Cipher.getInstance(AES);
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
		return cipher.doFinal(clear);
	}
	private static byte[] decrypt(byte[] raw, byte[] encrypted) throws Exception {
		SecretKeySpec skeySpec = new SecretKeySpec(raw, AES);
		Cipher cipher = Cipher.getInstance(AES);
		cipher.init(Cipher.DECRYPT_MODE, skeySpec);
		return cipher.doFinal(encrypted);
	}
	private static byte[] decodeByte(String hexStr) {
		byte[] bytes = new byte[hexStr.length() >> 1];
		for (int i = 0; i < bytes.length; i++) {
			char c1 = hexStr.charAt(i << 1);
			char c2 = hexStr.charAt(i << 1 | 1);
			// (a~f) - 'a' + 10 <=> (a~f)-'W'
			int x = c1 - (Character.isDigit(c1) ? '0' : 'W');
			bytes[i] = (byte) (x << 4 | (Character.isDigit(c2) ? c2 - '0' : c2 - 'W'));
		}
		return bytes;
	}
	public static String encodeHex(byte[] bytes) {
		StringBuilder sb = new StringBuilder(bytes.length << 1);
		for (byte b : bytes) {
			sb.append(HEX_CHARS[b >>> 4 & 15]);
			sb.append(HEX_CHARS[b & 15]);
		}
		return sb.toString();
	}

	private static String createToken(String tokenId){

		Algorithm algorithm = JwtUtil.hs256(null);
		Date nowTime = Calendar.getInstance().getTime();
		//失效日期
		Calendar calendar = Calendar.getInstance();
		calendar.add(Calendar.MINUTE, 30);
		Date expTime = calendar.getTime();


		HashMap<String,String> claimMap = new HashMap<>(1);
		claimMap.put("username", "李四");

		return JwtUtil.createToken("client", algorithm, nowTime, expTime, tokenId, UUID.randomUUID().toString(), claimMap);
	}

	public static void main(String[] args) throws Exception {
			String secret = "77A7A1D6-STST-40CC-U787-49EC3576XXXX";
			String data = "{\"id\":1000,\"type\":\"cxy\",\"prizeType\":1,\"amount\":2000,\"orderCode\":\"XXXXXX\"}";
			AESTool aesTool = new AESTool(secret);

			String encrypted = aesTool.encrypt(data);
			System.out.println(encrypted);

		String token = createToken("23425525344444455555555555555");
		System.out.println("token = " + aesTool.encrypt(token));
	}
}
